package com.admin.system.controller;

import com.admin.model.pojo.Menu;
import com.admin.model.dto.*;
import com.admin.model.vo.MenuMetaVo;
import com.admin.model.vo.MenuTreeVo;
import com.admin.monmon.util.SecurityConstants;
import com.admin.system.dao.RoleDao;
import com.admin.system.security.service.UserDetailsImpl;
import com.admin.system.security.service.UserDetailsServiceImpl;
import com.admin.system.service.MenuService;
import com.admin.system.service.mapstruct.MenuMapper;
import com.admin.system.security.jwt.SecurityUtils;
import com.admin.system.service.impl.AuthServiceImpl;
import com.admin.system.security.jwt.JwtTokenUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author caixiaofeng
 * @version 1.0
 * @Description: <<>>
 * @company cxf
 * @create 2021-01-27 23:06
 */
@Api(tags = "认证授权")
@RestController
@RequestMapping("/auth")
public class AuthController {
    @Resource
    private AuthServiceImpl authService;
    @Resource
    private JwtTokenUtils jwtTokenUtils;
    @Resource
    private RoleDao roleDao;
    @Resource
    private MenuService menuService;
    @Resource
    private MenuMapper menuMapper;
    //缓存用户菜单信息
    private static Map<String, List<MenuTreeVo>> menuCache = new ConcurrentHashMap<>();

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @GetMapping("/hello")
    public ResponseEntity<Object> hello() {
        return ResponseEntity.ok("我是资源1");
    }

    @PreAuthorize("hasRole('ROLE_USER')")
    @GetMapping("/hello2")
    public String hello2() {
        return "我是资源2";
    }

    /**
     * 登录认证
     *
     * @param authUserDto
     * @return
     */
    @ApiOperation("用户登录")
    @PostMapping("/login")
    public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUserDto) {
        String token = authService.login2(authUserDto);
        UserDetailsImpl UserDetailsImpl = (UserDetailsImpl) SecurityUtils.getCurrentUser();
        HashMap<String, Object> userInfo = new HashMap<>();
        userInfo.put("token", token);
        userInfo.put("user", UserDetailsImpl.getUser());

        Set<String> roles = UserDetailsImpl.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());

        userInfo.put("roles", roles);
        return ResponseEntity.ok(userInfo);
    }

    /**
     * 退出登录
     *
     * @return
     */
    @ApiOperation("退出登录")
    @PostMapping("/logout")
    public ResponseEntity<Object> logout(@RequestHeader(SecurityConstants.TOKEN_HEADER) String token) {
        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            throw new RuntimeException("当前登录状态过期");
        }

        if (authentication.getPrincipal() instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            String username = userDetails.getUsername();
            // 删除用户缓存内信息
            UserDetailsServiceImpl.clearCacheUser(username);
        }
        return ResponseEntity.ok("退出成功");
    }

    /**
     * 刷新令牌
     *
     * @param token
     * @return
     */
    @ApiOperation("刷新令牌")
    @PostMapping("/refreshToken")
    public ResponseEntity<String> refresh(@RequestHeader(SecurityConstants.TOKEN_HEADER) String token) {
        return ResponseEntity.ok(authService.refreshToken(token));
    }

    /**
     * 用户信息
     *
     * @return
     */
    @ApiOperation("获得用户信息")
    @GetMapping("/info")
    public ResponseEntity<Object> info() {
        UserDetailsImpl UserDetailsImpl = (UserDetailsImpl) SecurityUtils.getCurrentUser();
        if (!ObjectUtils.isEmpty(UserDetailsImpl)) {
            UserDto user = UserDetailsImpl.getUser();
            Set<String> roles = UserDetailsImpl.getAuthorities().stream()
                    .map(GrantedAuthority::getAuthority)
                    .collect(Collectors.toSet());
            HashMap<String, Object> infoMap = new HashMap<>();
            infoMap.put("user", user);
            infoMap.put("roles", roles);
            return ResponseEntity.status(HttpStatus.OK).body(infoMap);
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("账户信息不存在");
    }

    @ApiOperation("获得用户菜单")
    @GetMapping("/menuTree")
    public ResponseEntity<Object> menuList() {
        UserDetailsImpl user = (UserDetailsImpl) SecurityUtils.getCurrentUser();
        Assert.notNull(user, "用户登录信息不存在");
        if (menuCache.containsKey(user.getUsername())) {
            List<MenuTreeVo> menuTreeVos = menuCache.get(user.getUsername());
            return ResponseEntity.ok(menuTreeVos);
        }

        UserDto userDto = user.getUser();
        //查询出授权菜单
        List<Menu> menus = menuService.queryByUserId(userDto.getId());
        List<MenuTreeVo> tree = menuService.buildTree(menus);
        return ResponseEntity.ok(tree);
    }

}
